package services

import (
	"encoding/json"
	"fmt"
	"time"

	"cashew.com/cashew_api/dtos"
	"cashew.com/cashew_common/configs"
	"cashew.com/cashew_common/constants"
	"github.com/beego/beego/v2/core/logs"
)

type CocoCommonRespBody struct {
	Data   interface{} `json:"data"`
	Msg    string      `json:"msg"`
	Result int         `json:"result"`
}

type UserbalanceData struct {
	Balance string `json:"balance"`
}
type CocoUserbalanceRespBody struct {
	Data   UserbalanceData `json:"data"`
	Msg    string          `json:"msg"`
	Result int             `json:"result"`
}

type CocoUserInfoRespBody struct {
	Data   []CocoUserInfoItem `json:"data"`
	Msg    string             `json:"msg"`
	Result int                `json:"result"`
}

type CocoUserInfoItem struct {
	UserId       string `json:"user_id"`
	NickName     string `json:"nick_name"`
	AvatarUrl    string `json:"avatar_url"`
	Birthday     string `json:"birthday"`
	AnchorRating string `json:"anchor_rating"`
	FamilyId     string `json:"family_id"`
	FamilyName   string `json:"family_name"`
}

func GetCocoUserbalance(userId string) (respData *CocoUserbalanceRespBody, err error) {
	postUrl := configs.MasterApiHost + "/videocall/getuserbalance"
	headers := map[string]string{
		"Content-Type": "application/json",
	}

	// 构建完整的请求URL，将查询参数添加到URL中
	reqBody := map[string]interface{}{
		"user_id": userId,
	}

	respBody, err := HttpCall("POST", postUrl, headers, reqBody)
	if err != nil {
		return nil, err
	}
	logs.Debug("响应体数据:%s", string(respBody))

	respData = &CocoUserbalanceRespBody{}
	err = json.Unmarshal(respBody, &respData)
	if err != nil {
		return nil, err
	}

	return respData, nil
}

type AccountData struct {
	Balance string `json:"balance"`
	Score   string `json:"score"`
}
type CocoPayRespBody struct {
	Data   AccountData `json:"data"`
	Msg    string      `json:"msg"`
	Result int         `json:"result"`
}

// coco api 扣费接口
func CocoPay(userId string, anchorId string, amount int, score int) (respData *CocoPayRespBody, err error) {
	cocoApiUrl := configs.MasterApiHost + "/videocall/pay"
	headers := map[string]string{
		"Content-Type": "application/json",
	}
	reqBody := map[string]interface{}{
		"user_id":   userId,
		"touser_id": anchorId,
		"amount":    amount,
		"score":     score,
	}
	respBody, err := HttpCall("POST", cocoApiUrl, headers, reqBody)
	if err != nil {
		logs.Error("请求coco支付失败services.HttpCall(%s, %s, %+v, %+v): %v", "POST", cocoApiUrl, headers, reqBody, err)
		//c.Result(constants.ERR_PAY_FAILD, nil)
		return nil, err
	}

	respData = &CocoPayRespBody{}
	err = json.Unmarshal(respBody, &respData)
	if err != nil {
		//c.Result(constants.ERR_PARAM, nil)
		return nil, err
	}

	return respData, nil
}

type Odds struct {
	Addcoin  int `json:"addcoin"`
	Sum      int `json:"sum"`
	Odds10   int `json:"odds10"`
	Odds50   int `json:"odds50"`
	Odds500  int `json:"odds500"`
	Odds1000 int `json:"odds1000"`
	PropId   int `json:"prop_id"`
}

type SendGiftRespBody struct {
	Data   AccountData `json:"data"`
	Msg    string      `json:"msg"`
	Result int         `json:"result"`
	Odds   Odds        `json:"odds"`
}

// coco api 扣费接口
func CocoSendGift(userId string, anchorId string, propId int, propNum int) (respData *SendGiftRespBody, err error) {
	masterApiUrl := configs.MasterApiHost + "/videocall/sendgift"
	headers := map[string]string{
		"Content-Type": "application/json",
	}
	reqBody := map[string]interface{}{
		"user_id":   userId,
		"anchor_id": anchorId,
		"prop_id":   propId,
		"prop_num":  propNum,
	}
	respBody, err := HttpCall("POST", masterApiUrl, headers, reqBody)
	if err != nil {
		logs.Error("请求coco送礼接口失败services.HttpCall(%s, %s, %+v, %+v): %v", "POST", masterApiUrl, headers, reqBody, err)
		//c.Result(constants.ERR_PAY_FAILD, nil)
		return nil, err
	}

	respData = &SendGiftRespBody{}
	err = json.Unmarshal(respBody, &respData)
	if err != nil {
		//c.Result(constants.ERR_PARAM, nil)
		return nil, err
	}

	return respData, nil
}

// coco api 登录校验接口
func CocoVerifyuser(userId string, token string) (respData *CocoCommonRespBody, err error) {
	masterApiUrl := configs.MasterApiHost + "/videocall/verifyuser"
	headers := map[string]string{
		"Content-Type": "application/json",
	}
	reqBody := map[string]interface{}{
		"user_id": userId,
		"token":   token,
	}
	respBody, err := HttpCall("POST", masterApiUrl, headers, reqBody)
	if err != nil {
		logs.Error("请求coco登录校验接口失败services.HttpCall(%s, %s, %+v, %+v): %v", "POST", masterApiUrl, headers, reqBody, err)
		return nil, err
	}

	respData = &CocoCommonRespBody{}
	err = json.Unmarshal(respBody, &respData)
	if err != nil {
		//c.Result(constants.ERR_PARAM, nil)
		return nil, err
	}

	return respData, nil
}

func CocoGetUserinfo(userIdList []string) (*[]CocoUserInfoItem, error) {
	postUrl := configs.MasterApiHost + "/videocall/search"
	headers := map[string]string{
		"Content-Type": "application/json",
	}

	// 构建完整的请求URL，将查询参数添加到URL中
	reqBody := map[string]interface{}{
		"User_id": userIdList,
	}

	respBody, err := HttpCall("POST", postUrl, headers, reqBody)
	if err != nil {
		return nil, err
	}
	logs.Debug("响应体数据:%s", string(respBody))

	respData := &CocoUserInfoRespBody{}
	err = json.Unmarshal(respBody, &respData)
	if err != nil {
		return nil, err
	}

	if respData.Result != 0 {
		return nil, fmt.Errorf("请求失败，状态码: %d，响应消息: %s", respData.Result, respData.Msg)
	}

	list := respData.Data

	return &list, nil
}

type CocoPushMessageBody struct {
	NotifyTitle   string    `json:"notifyTitle"`
	NotifyContent string    `json:"notifyContent"`
	FromUser      *FromUser `json:"fromUser"`
}

// type CocoPushMessageResp struct
//
// }
type CocoPushMessageReq struct {
	Topic   string              `json:"topic"`
	Type    string              `json:"type"`
	ToUser  string              `json:"toUser"`
	Message CocoPushMessageBody `json:"message"`
}

func AssembleCocoPushMessageReq(identity int, req *dtos.SendChatParams, viewerInfo *UserCache, anchorInfo *UserCache) (assembledReq *CocoPushMessageReq, err error) {
	if req == nil || viewerInfo == nil || anchorInfo == nil {
		return nil, fmt.Errorf("参数不能为空")
	}

	assembledReq = &CocoPushMessageReq{
		Topic:  "all",
		ToUser: req.ToUserId,
		Type:   fmt.Sprintf("%d", constants.COCO_PUSH_MSG_NOTIFY_TYPE_IM), // 目前只有这一种类型
	}

	var fromUser FromUser
	if identity == constants.IDENTITY_NORMAL_USER {
		fromUser.UserId = fmt.Sprintf("%d", viewerInfo.UserId)
		fromUser.Nick = viewerInfo.Nick
		fromUser.HeadImg = viewerInfo.HeadImg
		fromUser.Age = viewerInfo.Age
		fromUser.FlagImage = viewerInfo.FlagImage
		fromUser.Gender = viewerInfo.Gender
	} else {
		fromUser.UserId = fmt.Sprintf("%d", anchorInfo.UserId)
		fromUser.Nick = anchorInfo.Nick
		fromUser.HeadImg = anchorInfo.HeadImg
		fromUser.Age = anchorInfo.Age
		fromUser.FlagImage = anchorInfo.FlagImage
		fromUser.Gender = anchorInfo.Gender
	}
	assembledReq.Message.FromUser = &fromUser
	assembledReq.Message.NotifyTitle = fromUser.Nick

	switch req.MsgType {
	case constants.CHAT_MSG_TYPE_TEXT:
		assembledReq.Message.NotifyContent = TruncateString(req.Msg, 20)
	case constants.CHAT_MSG_TYPE_PIC:
		assembledReq.Message.NotifyContent = "图片消息"
	case constants.CHAT_MSG_TYPE_AUDIO:
		assembledReq.Message.NotifyContent = "语音消息"
	case constants.CHAT_MSG_TYPE_VIDEO:
		assembledReq.Message.NotifyContent = "视频消息"
	default:
		assembledReq.Message.NotifyContent = "未知消息类型"
	}

	return assembledReq, nil
}

// 取消聊天限制 使用 coco 推送 请求组装(用户端调用)
func AssembleCocoPushMessageReq3(req *dtos.SendChatParams, fromUserCatchInfo *UserCache) (assembledReq *CocoPushMessageReq, err error) {
	if req == nil || fromUserCatchInfo == nil {
		return nil, fmt.Errorf("参数不能为空")
	}

	assembledReq = &CocoPushMessageReq{
		Topic:  "all",
		ToUser: req.ToUserId,
		Type:   fmt.Sprintf("%d", constants.COCO_PUSH_MSG_NOTIFY_TYPE_IM), // 目前只有这一种类型
	}

	var fromUser FromUser
	fromUser.UserId = fmt.Sprintf("%d", fromUserCatchInfo.UserId)
	fromUser.Nick = fromUserCatchInfo.Nick
	fromUser.HeadImg = fromUserCatchInfo.HeadImg
	fromUser.Age = fromUserCatchInfo.Age
	fromUser.FlagImage = fromUserCatchInfo.FlagImage
	fromUser.Gender = fromUserCatchInfo.Gender

	assembledReq.Message.FromUser = &fromUser
	assembledReq.Message.NotifyTitle = fromUser.Nick

	switch req.MsgType {
	case constants.CHAT_MSG_TYPE_TEXT:
		assembledReq.Message.NotifyContent = TruncateString(req.Msg, 20)
	case constants.CHAT_MSG_TYPE_PIC:
		assembledReq.Message.NotifyContent = "图片消息"
	case constants.CHAT_MSG_TYPE_AUDIO:
		assembledReq.Message.NotifyContent = "语音消息"
	case constants.CHAT_MSG_TYPE_VIDEO:
		assembledReq.Message.NotifyContent = "视频消息"
	default:
		assembledReq.Message.NotifyContent = "未知消息类型"
	}

	return assembledReq, nil
}

// 自由聊天 使用 coco 推送 请求组装(服务端调用,用户详情来自coco,1v1里不可查)
func AssembleCocoPushMessageReq2(identity int, req *dtos.SendMessageParams) (assembledReq *CocoPushMessageReq, err error) {
	if req == nil {
		return nil, fmt.Errorf("参数不能为空")
	}

	assembledReq = &CocoPushMessageReq{
		Topic:  "all",
		ToUser: req.ToUserId,
		Type:   fmt.Sprintf("%d", constants.COCO_PUSH_MSG_NOTIFY_TYPE_IM), // 目前只有这一种类型
	}

	var fromUser FromUser

	fromUserInfo := req.UserInfo

	if fromUserInfo != nil {
		fromUser.UserId = fromUserInfo.UserID
		fromUser.Nick = fromUserInfo.Nick
		fromUser.HeadImg = fromUserInfo.HeadImg
		fromUser.Age = fromUserInfo.Age
		fromUser.FlagImage = fromUserInfo.FlagImage
		fromUser.Gender = fromUserInfo.Gender
	} else {
		// 查我们的数据库缓存 todo ...
	}
	assembledReq.Message.FromUser = &fromUser
	assembledReq.Message.NotifyTitle = fromUser.Nick

	switch req.MsgType {
	case constants.CHAT_MSG_TYPE_TEXT:
		assembledReq.Message.NotifyContent = TruncateString(req.Msg, 20)
	case constants.CHAT_MSG_TYPE_PIC:
		assembledReq.Message.NotifyContent = "图片消息"
	case constants.CHAT_MSG_TYPE_AUDIO:
		assembledReq.Message.NotifyContent = "语音消息"
	case constants.CHAT_MSG_TYPE_VIDEO:
		assembledReq.Message.NotifyContent = "视频消息"
	default:
		assembledReq.Message.NotifyContent = "未知消息类型"
	}

	return assembledReq, nil
}

type CocoPushMessage struct {
	Type    int          `json:"type"`
	Message InnerMessage `json:"message"`
}

type InnerMessage struct {
	NotifyType    int       `json:"notifyType"`
	NotifyTitle   string    `json:"notifyTitle"`
	NotifyContent string    `json:"notifyContent"`
	FromUser      *FromUser `json:"fromUser"`
}

type FromUser struct {
	UserId    string `json:"user_id"`
	Nick      string `json:"nick"`
	HeadImg   string `json:"head_img"`
	Age       int    `json:"age"`
	FlagImage string `json:"flag_image"`
	Gender    int    `json:"gender"`
}

type CocoPushRespBody struct {
	Result int         `json:"result"`
	Msg    string      `json:"msg"`
	Data   interface{} `json:"data"`
}

// 安卓通知
func CocoPush(req *CocoPushMessageReq) (respData *CocoPushRespBody, err error) {
	logs.Debug("CocoPush 请求参数: %+v", req)

	masterApiUrl := configs.MasterApiHost + "/firebase/sendmessage"
	headers := map[string]string{
		"Content-Type": "application/json",
	}

	jsonBytes, err := json.Marshal(req.Message)
	if err != nil {
		logs.Error("请求coco firebase发消息接口报错 json.Marshal(%+v): %v", req.Message, err)
		return
	}
	pushMessage := string(jsonBytes)

	reqBody := map[string]interface{}{
		"topic":   req.Topic,
		"type":    req.Type,
		"toUser":  req.ToUser,
		"message": pushMessage,
	}

	respBody, err := HttpCall("POST", masterApiUrl, headers, reqBody)
	if err != nil {
		logs.Error("请求coco firebase发消息接口报错 services.HttpCall(%s, %s, %+v, %+v): %v", "POST", masterApiUrl, headers, reqBody, err)
		return nil, err
	}
	logs.Info("CocoPush 接口响应数据: %s", string(respBody))

	respData = &CocoPushRespBody{}
	err = json.Unmarshal(respBody, &respData)
	if err != nil {
		logs.Error("解析Coco推送接口响应数据失败: %v", err)
		return nil, err
	}

	return respData, nil
}

func VideocallSearch(userId string) (*[]dtos.MaterApiVideocallSearchData, error) {
	postUrl := configs.MasterApiHost + "/videocall/search"
	headers := map[string]string{
		"Content-Type": "application/json",
	}

	// 构建完整的请求URL，将查询参数添加到URL中
	reqBody := map[string]interface{}{
		"user_id": []string{userId},
	}

	respBody, err := HttpCall("POST", postUrl, headers, reqBody)
	if err != nil {
		return nil, err
	}

	respData := &[]dtos.MaterApiVideocallSearchData{}
	err = parseCocoResult(respBody, respData)
	if err != nil {
		return nil, err
	}

	return respData, nil
}

func parseCocoResult[T any](respBody []byte, data *T) error {
	var resp map[string]interface{}
	err := json.Unmarshal(respBody, &resp)
	if err != nil {
		return fmt.Errorf("解析响应数据失败: %v", err)
	}

	result, okResult := resp["result"].(float64)
	msg, okMsg := resp["msg"].(string)

	if !okResult {
		return fmt.Errorf("解析code失败: %v", err)
	}

	if !okMsg {
		return fmt.Errorf("解析msg失败: %v", err)
	}

	if int(result) != 0 {
		return fmt.Errorf("请求失败, result=%d，msg=%s", result, msg)
	}

	if data != nil {
		var dataBytes []byte
		dataBytes, err = json.Marshal(resp["data"])
		if err != nil {
			return fmt.Errorf("请求成功, 解析data失败: %v", err)
		}

		err = json.Unmarshal(dataBytes, data)
		if err != nil {
			return fmt.Errorf("请求成功, 解析data失败: %v", err)
		}
	}

	return nil
}

// 测试用慢响应接口(待删除)
func CocoPush2(userId int64, msg string) (respData *CocoPushRespBody, err error) {
	// 创建一个每隔1秒触发一次的定时器
	ticker := time.NewTicker(3 * time.Second)
	defer ticker.Stop()

	startTime := time.Now()
	for {
		// 每次触发时执行一些耗时操作，比如打印信息（可替换为真实业务逻辑）
		logs.Info("我是用户 userId:%d 的 CocoPush2 协程,msg:%s", userId, msg)
		// 模拟一些复杂计算，这里简单用一个自增变量做耗时操作示例
		var sum int
		for i := 0; i < 10000000; i++ {
			sum += i
		}

		// 判断是否达到模拟的处理时间，比如这里模拟最长处理60秒
		if time.Since(startTime) > 60*time.Second {
			break
		}

		// 等待下一次定时器触发
		<-ticker.C
	}
	return
}
